package mq

import (
	"github.com/spf13/viper"
	"github.com/streadway/amqp"
)

type RabbitMQ struct {
	conn    *amqp.Connection
	channel *amqp.Channel
	//队列名字
	QueueName string
	//交换机
	Exchange string
	//key
	Key string
	//连接信息
	Mqurl string
}

func NewRabbitMQ(queueName, exchange, key string) (*RabbitMQ, error) {
	rabbitmq := &RabbitMQ{
		QueueName: queueName,
		Exchange:  exchange,
		Key:       key,
		Mqurl:     viper.GetString("rabbitmq.dsn"),
	}

	var err error
	//创建rabbitmq连接
	if rabbitmq.conn, err = amqp.Dial(rabbitmq.Mqurl); err != nil {
		return nil, err
	}
	if rabbitmq.channel, err = rabbitmq.conn.Channel(); err != nil {
		return nil, err
	}
	return rabbitmq, nil
}

// 断开连接
func (r *RabbitMQ) Destroy() {
	r.conn.Close()
	r.channel.Close()
}

// 死信模式1.
func NewRabbitMQDead(queueName, exchangeName, routingKey string) (*RabbitMQ, error) {
	return NewRabbitMQ(queueName, exchangeName, routingKey)
}
func (r *RabbitMQ) InitExchange() error {
	//1.尝试创建交换机
	err := r.channel.ExchangeDeclare(
		r.Exchange,
		"direct",
		true,
		false,
		//true表示这个exchange不可以被client用来推送消息，仅用来进行exchange和exchange之间的绑定
		false,
		false,
		nil,
	)
	return err
}
func (r *RabbitMQ) PublishDead() error {
	//2.申请队列，如果队列不存在会自动创建，如果存在则跳过创建
	//保证队列存在，消息能发送到队列中
	q, err := r.channel.QueueDeclare(
		"order.delay", //随机生产队伍名称
		true,
		false,
		false,
		false,
		amqp.Table{
			"x-dead-letter-exchange":    r.Exchange,      // 死信交换机
			"x-dead-letter-routing-key": "release.order", // 死信路由键
			"x-message-ttl":             10000,
		}, // 其他参数,
	)
	if err != nil {
		return err
	}

	//3.绑定队列到exchange中
	if err = r.channel.QueueBind(
		q.Name,
		"create.order",
		r.Exchange,
		false,
		nil,
	); err != nil {
		return err
	}

	//2.申请队列，如果队列不存在会自动创建，如果存在则跳过创建
	//保证队列存在，消息能发送到队列中
	q1, err := r.channel.QueueDeclare(
		"order.release", //随机生产队伍名称
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		return err
	}

	//3.绑定队列到exchange中
	if err = r.channel.QueueBind(
		q1.Name,
		"release.order",
		r.Exchange,
		false,
		nil,
	); err != nil {
		return err
	}
	return nil
}

func (r *RabbitMQ) PublishDeadMsg(msg []byte) error {
	err := r.channel.Publish(
		r.Exchange,
		"create.order",
		false,
		false,
		amqp.Publishing{
			DeliveryMode: amqp.Persistent,
			ContentType:  "text/plain", //纯文本
			Body:         msg,
		})
	return err
}
func (r *RabbitMQ) RecieveDead() (<-chan amqp.Delivery, error) {
	//1.尝试创建交换机
	var q amqp.Queue
	var err error
	//2.申请队列，如果队列不存在会自动创建，如果存在则跳过创建
	//保证队列存在，消息能发送到队列中
	q, err = r.channel.QueueDeclare(
		"order.release", //随机生产队伍名称
		true,
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		return nil, err
	}

	//4.消费
	msgs, err := r.channel.Consume(
		q.Name,
		"",
		false, //自动应答
		false,
		false,
		false,
		nil,
	)
	return msgs, nil
}

func NewRabbitMQTopic(queueName, exchangeName, routingKey string) (*RabbitMQ, error) {
	return NewRabbitMQ(queueName, exchangeName, routingKey)
}
func (r *RabbitMQ) PublishMsg(msg []byte) error {
	//2.发送消息
	err := r.channel.Publish(
		r.Exchange,
		r.Key, //要设置
		false,
		false,
		amqp.Publishing{
			ContentType: "text/plain", //纯文本
			Body:        msg,
		},
	)
	return err
}

// 路由模式：3.消费
func (r *RabbitMQ) RecieveRouting() (<-chan amqp.Delivery, error) {
	//2.申请队列，如果队列不存在会自动创建，如果存在则跳过创建
	//保证队列存在，消息能发送到队列中
	var (
		q   amqp.Queue
		err error
	)
	if q, err = r.channel.QueueDeclare(
		"reback_order.queue", //随机生产队伍名称
		true,
		false,
		false,
		false,
		nil,
	); err != nil {
		return nil, err
	}

	//3.绑定队列到exchange中
	if err = r.channel.QueueBind(
		q.Name,
		r.Key,
		r.Exchange,
		false,
		nil,
	); err != nil {
		return nil, err
	}

	//4.消费
	msgs, err := r.channel.Consume(
		q.Name,
		"",
		false, //自动应答
		false,
		false,
		false,
		nil,
	)
	if err != nil {
		return nil, err
	}

	return msgs, nil
}
